/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */

package org.apache.mina.protocol.dns.messages;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * All communications inside of the domain protocol are carried in a single
 * format called a message. The top level format of message is divided into 5
 * sections (some of which are empty in certain cases) shown below:
 * 
 * <pre>
 * +---------------------+ 
 * | Header              | 
 * +---------------------+ 
 * | Question            | the question for the name server 
 * +---------------------+ 
 * | Answer              | ResourceRecords answering the question 
 * +---------------------+ 
 * | Authority           | ResourceRecords pointing toward an authority 
 * +---------------------+ 
 * | Additional          | ResourceRecords holding additional information
 * +---------------------+
 * </pre>
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev: 84 $, $Date: 2008-02-22 16:33:48 +0000 (Fri, 22 Feb 2008) $
 */
public class DnsMessage {
    /**
     * The header section is always present. The header includes fields that
     * specify which of the remaining sections are present, and also specify
     * whether the message is a query or a response, a standard query or some
     * other opcode, etc.
     */
    private int transactionId;

    private MessageType messageType;

    private OpCode opCode;

    private boolean authoritativeAnswer;

    private boolean truncated;

    private boolean recursionDesired;

    private boolean recursionAvailable;

    private boolean reserved;

    private boolean acceptNonAuthenticatedData;

    private ResponseCode responseCode;

    private List<QuestionRecord> questionRecords;

    private List<ResourceRecord> answerRecords;

    private List<ResourceRecord> authorityRecords;

    private List<ResourceRecord> additionalRecords;

    /**
     * Creates a new instance of DnsMessage.
     * 
     * @param transactionId
     * @param messageType
     * @param opCode
     * @param authoritativeAnswer
     * @param truncated
     * @param recursionDesired
     * @param recursionAvailable
     * @param reserved
     * @param acceptNonAuthenticatedData
     * @param responseCode
     * @param question
     * @param answer
     * @param authority
     * @param additional
     */
    public DnsMessage(int transactionId, MessageType messageType,
            OpCode opCode, boolean authoritativeAnswer, boolean truncated,
            boolean recursionDesired, boolean recursionAvailable,
            boolean reserved, boolean acceptNonAuthenticatedData,
            ResponseCode responseCode, List<QuestionRecord> question,
            List<ResourceRecord> answer, List<ResourceRecord> authority,
            List<ResourceRecord> additional) {
        this.transactionId = transactionId;
        this.messageType = messageType;
        this.opCode = opCode;
        this.authoritativeAnswer = authoritativeAnswer;
        this.truncated = truncated;
        this.recursionDesired = recursionDesired;
        this.recursionAvailable = recursionAvailable;
        this.reserved = reserved;
        this.acceptNonAuthenticatedData = acceptNonAuthenticatedData;
        this.responseCode = responseCode;
        this.questionRecords = question;
        this.answerRecords = answer;
        this.authorityRecords = authority;
        this.additionalRecords = additional;
    }

    static List<ResourceRecord> emptyResourceList = Collections
            .unmodifiableList(new ArrayList<ResourceRecord>());

    public static DnsMessage newDnsQuery(int transactionid, String host) {
        QuestionRecord qr = new QuestionRecord(host, RecordType.A,
                RecordClass.IN);
        List<QuestionRecord> qrList = new ArrayList<QuestionRecord>();
        qrList.add(qr);

        return new DnsMessage(transactionid, MessageType.QUERY, OpCode.QUERY,
                false, false, true, false, false, false, ResponseCode.NO_ERROR,
                qrList, emptyResourceList, emptyResourceList, emptyResourceList);
    }

    /**
     * @return Returns the acceptNonAuthenticatedData.
     */
    public boolean isAcceptNonAuthenticatedData() {
        return acceptNonAuthenticatedData;
    }

    /**
     * @return Returns the additional.
     */
    public List<ResourceRecord> getAdditionalRecords() {
        return additionalRecords;
    }

    /**
     * @return Returns the answers.
     */
    public List<ResourceRecord> getAnswerRecords() {
        return answerRecords;
    }

    /**
     * @return Returns the authoritativeAnswer.
     */
    public boolean isAuthoritativeAnswer() {
        return authoritativeAnswer;
    }

    /**
     * @return Returns the authority.
     */
    public List<ResourceRecord> getAuthorityRecords() {
        return authorityRecords;
    }

    /**
     * @return Returns the messageType.
     */
    public MessageType getMessageType() {
        return messageType;
    }

    /**
     * @return Returns the opCode.
     */
    public OpCode getOpCode() {
        return opCode;
    }

    /**
     * @return Returns the question.
     */
    public List<QuestionRecord> getQuestionRecords() {
        return questionRecords;
    }

    /**
     * @return Returns the recursionAvailable.
     */
    public boolean isRecursionAvailable() {
        return recursionAvailable;
    }

    /**
     * @return Returns the recursionDesired.
     */
    public boolean isRecursionDesired() {
        return recursionDesired;
    }

    /**
     * @return Returns the reserved.
     */
    public boolean isReserved() {
        return reserved;
    }

    /**
     * @return Returns the responseCode.
     */
    public ResponseCode getResponseCode() {
        return responseCode;
    }

    /**
     * @return Returns the transactionId.
     */
    public int getTransactionId() {
        return transactionId;
    }

    /**
     * @return Returns the truncated.
     */
    public boolean isTruncated() {
        return truncated;
    }

}
